<template>
  <el-card class="margin-top hot-table">
    <div slot="header" class="head-main flex justify-between align-center">
      <div>
        <span class="title-icon margin-right-sm">{{
          $t('waybill.customsClearanceInvoice')
        }}</span>
        <span> (请注意采购单价币种与申报币种不一致) </span>
        <span
          v-if="orderType !== 'quickOrder'"
          class="head-btn"
          @click="clickBatch"
        >
          批量导入箱单发票
        </span>
        <el-tooltip
          class="margin-left-sm"
          content="该功能只能恢复当前电脑的最近一次发票数据。"
          placement="top"
          effect="light"
        >
          <span class="head-btn margin-left-sm" @click="restoreInvoiceData">
            恢复发票内容
          </span>
        </el-tooltip>
        <!-- 批量导入SKU图片 -->
        <span class="head-btn margin-left-sm" @click="showSkuList">
          选择SKU
        </span>
        <span class="head-btn margin-left-sm" @click="upLoadImg(0)">
          批量上传SKU图片
        </span>
        <span
          v-if="isJapan"
          class="head-btn margin-left-sm"
          @click="upLoadImg(1)"
        >
          批量上传售价截图
        </span>
        <span
          v-if="isJapan"
          class="head-btn margin-left-sm"
          @click="upLoadImg(2)"
        >
          批量上传收益截图
        </span>
      </div>
      <div class="">
        <el-row>
          <el-col :span="10">
            <span class="head-btn" @click="resetInvoice"> 重置发票内容 </span>
          </el-col>
          <el-col :span="14">
            <el-row class="flex align-center">
              <el-col :span="10">
                <span>申报币种：</span>
              </el-col>
              <el-col :span="14">
                <el-select
                  v-model="invoiceInfoData.declareValueCurrency"
                  size="mini"
                  filterable
                  placeholder="请选择"
                >
                  <el-option
                    v-for="(item, value) in currencyMap"
                    :key="value"
                    :label="item"
                    :value="value"
                  />
                </el-select>
              </el-col>
            </el-row>
          </el-col>
        </el-row>
      </div>
    </div>

    <hot-table ref="hotTable" :settings="hotSettings" />

    <div class="padding text-center">
      <el-button type="success" @click.native="addEmptyData">
        添加品名
      </el-button>
    </div>

    <!-- 批量导入箱单发票 -->
    <el-dialog
      title="批量导入箱单发票"
      :visible.sync="showUploadInvoice"
      width="66%"
      :before-close="handleClose"
      class="upload-Invoice-dialog"
    >
      <div class="flex align-center justify-around down-btn flex-wrap">
        <a href="./excel/下载导入模板(适合FBA下单).xlsx">
          下载导入模板(适合FBA下单)
        </a>
        <a href="./excel/下载导入模板(适合非FBA下单).xlsx">
          下载导入模板(适合非FBA下单)
        </a>
        <a href="./excel/下载导入模板(适合FBC下单).xlsx">
          下载导入模板(适合FBC下单)
        </a>
        <a href="./excel/下载导入模板(适合非FBA，sku同款下单).xlsx">
          下载导入模板(适合非FBA，sku同款下单)
        </a>
        <a v-if="isJapan" href="./excel/下载导入模板(适合日本线下单).xlsx">
          下载导入模板(适合日本线下单)
        </a>
      </div>
      <div class="Invoice-dialog-tips-icon">
        <el-tooltip class="item" effect="light" placement="right">
          <div slot="content" style="line-htight: 1.8">
            ①有新模板导入若多个SKU箱号相同，箱号，长，宽，高，重列请合并单元格；
            <br>
            <br>
            ②上传时请仔细检查模板数据,FBA需要填写Shipment ID，Reference ID；
            <br>
            <br>
            ③如果系统收入客户SKU信息，会自动补全部分缺损部分
          </div>
          <i class="el-icon-question icon-question text-yellow" />
        </el-tooltip>
      </div>
      <el-upload
        ref="upload"
        class="upload-demo"
        :limit="1"
        drag
        action="#"
        :auto-upload="false"
        :http-request="uploadFn"
        :file-list="fileList"
      >
        <i class="el-icon-upload" />
        <div class="el-upload__text">
          将文件拖到此处，或<em>点击上传</em>，支持多文件同时上传
          <br>
          <br>

          <span class="upload-tips">
            请您及时上传报关资料，如果不及时上传，系统会做扣货处理。
          </span>
        </div>
        <!-- <div slot="tip" class="el-upload__tip">只能上传jpg/png文件，且不超过500kb</div> -->
      </el-upload>
      <span slot="footer" class="dialog-footer">
        <el-button @click="showUploadInvoice = false">取 消</el-button>
        <el-button type="primary" :loading="showLoading" @click="submitUpload">
          上传到服务器
        </el-button>
      </span>
    </el-dialog>
    <!-- 批量导入箱单发票 -->
    <el-dialog
      title="选择SKU"
      :visible.sync="showSkuListVisible"
      :before-close="handleClose"
      width="80%"
    >
      <SkuInfo
        :create-order="true"
        :show-sku-list-visible.sync="showSkuListVisible"
        :multiple-selection-sku.sync="multipleSelectionSku"
      />
    </el-dialog>
    <!-- 上传图片 -->
    <UploadImg
      :show-upload-img.sync="showUploadImg"
      :rule-form.sync="ruleForm"
      :url="`/seaair/waybills/uploadImage`"
      @getImgUrl="getImgUrl"
    />
    <!-- 批量上传图片 -->
    <UploadImg2
      :show-upload-img.sync="showUploadImg2"
      :waybill-id="waybillId"
      :url="`/seaair/waybills/` + urlList[urlListIndex]"
      @getImgUrl="getImgUrl2"
    />
  </el-card>
</template>

<script>
import { HotTable } from '@handsontable/vue'
import Handsontable from 'handsontable'
import 'handsontable/languages/zh-CN'
import globalData from '@/utils/config'
import { mapGetters } from 'vuex'
import {
  otherHeader,
  JapanLineHeader,
  colHeaders,
  fbaHead,
  noFbaHead,
  getSpanArr
} from '@/utils/invoice-table'
import { clone } from '@/utils/clone'
import { getToken } from '@/utils/auth'
import { doImportLiquidationPacking, queryApiSkuInfos } from '@/api/waybill'
import UploadImg from '@/components/uploadImg'
import UploadImg2 from '@/components/uploadImg2'
import { isNoEmptyObject, checkRowsEmpty } from '@/utils/waybill-public'
import { customerskuinfoList } from '@/api/myProfile'
import SkuInfo from '@/views/myProfile/skuInfo'
export default {
  name: 'Invoice',
  components: {
    HotTable,
    UploadImg,
    UploadImg2,
    SkuInfo
  },
  props: {
    orderType: {
      type: String,
      default: 'quickOrder'
    },
    waybillId: {
      type: String,
      default: ''
    },
    waybillCode: {
      type: String,
      default: ''
    },
    showTips: {
      type: String,
      default: ''
    },
    invoiceTableInfo: {
      type: Object,
      default: function() {
        return {}
      }
    }
  },
  data() {
    return {
      urlList: [
        'batchUploadSkuImage',
        'batchUploadSellpriceScreenshotImage',
        'batchUploadIncomeScreenshotImage'
      ],
      urlListIndex: 0,
      fileUrl: globalData.fileUrl,
      fileList: [],
      multipleSelectionSku: [],
      timerFlag: false,
      timer: null,
      timer2: null,
      showUploadInvoice: false,
      showSkuListVisible: false,
      showUploadImg: false,
      showUploadImg2: false,
      showImgDialog: false,
      dialogVisible: false,
      returnChange: false, // 阻止改变
      showLoading: false, //
      ruleForm: {
        coverFile: '',
        coverUrl: ''
      },
      invoiceInfoData: {
        oldPackingInfo: [],
        oldTableData: [],
        declareValueCurrency: 'USD', // 币种
        tableData: [{}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}]
      },
      listData: [],
      currencyMap: {
        USD: 'USD'
      },
      selectSkuList: [],
      skuUnit: []
    }
  },

  computed: {
    ...mapGetters([
      'channelFormLeft',
      'invoiceInfo',
      'packingInfo',
      'waybillRender',
      'publicData',
      'createTpye',
      'name'
    ]),
    isJapan() {
      return (
        this.publicData.countryMap &&
        this.channelFormLeft.countryId &&
        this.publicData.countryMap[this.channelFormLeft.countryId] &&
        this.publicData.countryMap[this.channelFormLeft.countryId].indexOf(
          '日本'
        ) !== -1
      )
    },
    autoHeight() {
      return this.invoiceInfoData.tableData.length > 16 ? '420px' : 'auto'
    },
    hotSettings() {
      return {
        currentRowClassName: 'currentRow', // 为选中行添加类名，可以更改样式
        currentColClassName: 'currentCol', // 为选中列添加类名
        rowHeaders: true, // 行表头
        // headerTooltips: true, // 鼠标划过头部时的提示文字
        data: this.invoiceInfoData.tableData,
        stretchH: 'all', // 所有列宽小于表宽时,填充满整个表 all（所有列填充）/last（最后一列）/none(不填充)
        licenseKey: globalData.licensekey,
        // 定义表结构
        colHeaders: this.setHeader(),
        width: '100%',
        height: this.autoHeight,
        // TODO
        columns: this.buildColumns(this.isJapan),
        tableClassName: ['first-class-name', 'second-class-name'],
        language: 'zh-CN',
        contextMenu: true, // 开启右键菜单
        // 实例化之后
        // afterInit: () => {
        //   console.log('afterInit')
        // },
        // 改变前

        /**
         * @description:
         * @param {Number} row 数据第几行
         * @param {String} prop 参数名
         * @param {*} oldValue 该参数名 旧数据
         * @param {*} newValue 该参数名 新数据
         * @return {*}
         */
        beforeChange: async(changes, source) => {
          console.log('changes :>> ', changes)
          if (!changes) return
          const [row, prop, oldValue, newValue] = changes[0]
          if (oldValue === newValue) {
            changes.length = 0
            return
          }
          if (['customsClearanceCode', 'customsCode'].includes(prop) && newValue.indexOf('.') > -1 && newValue.length > 11) {
            this.$message.warning('限制在10个字符以内')
            changes.length = 0
            return
          }
          console.log('newValue.length :>> ', newValue.length)
          if (['customsClearanceCode', 'customsCode'].includes(prop) && newValue.indexOf('.') === -1 && newValue.length > 10) {
            this.$message.warning('限制在10个字符以内')
            changes.length = 0
            return
          }
          // if (!this.channelFormLeft.inStockChannel) {
          //   this.$message.error('请先选择渠道！')
          //   changes.length = 0
          //   return
          // }
        },

        // 改变后
        afterChange: async(changes, source) => {
          /**
           * 1.发票表格修改 该行2,12 存在既满足修改条件
           */
          // return
          if (!changes) return
          this.checkTableData()

          const oldData = this.invoiceInfoData.oldTableData
          if (changes.length > 0) {
            // let delArr = []
            for (const i of changes) {
              const [row, prop, oldValue, newValue] = i
              // 判断 shk 、 num, 有旧数据，但是新数据为空
              if (
                (prop === 'sku' && !newValue && oldValue && oldData[row].num) ||
                (prop === 'num' && !newValue && oldValue && oldData[row].sku)
              ) {
                // delArr.push(oldData[row].sku)
                await this.delPackingData(oldData[row])
              }
              this.afterChangeTable(i)
            }
            // console.log('delArr :>> ', delArr)
            // 如果存在删除的数据
            // if (delArr.length === 0) {
            //   this.afterChangeTable(changes[0])
            //   // this.afterChangeTable(i)
            // }
          } else {
            this.afterChangeTable(changes[0])
          }
          // }

          if (!this.timerFlag) {
            // 缓存发票信息
            this.timer = setInterval(() => {
              if (this.invoiceInfoData.tableData) {
                let str = ''
                if (this.waybillId) {
                  str = this.waybillId
                } else {
                  str = this.waybillCode
                }
                sessionStorage.setItem(
                  `tableInvoice-${str}`,
                  JSON.stringify(this.invoiceInfoData.tableData)
                )
              }
              // console.log('保存发票临时数据 :>> 10s ')
            }, 10000)
          }
          this.timerFlag = true
        },
        // 单击之后
        afterOnCellMouseDown: (event, coords, TD) => {
          this.coords = coords
        },

        /**
         * [一行或者多行移除后触发]
         * @param  {[number]} index        [起始行的可视索引]
         * @param  {[number]} amount       [删除行的数量]
         * @param  {[array]}  physicalRows [被删除行的数据组成的数组]
         * @param  {[string]} source       [触发的源]
         */
        afterRemoveRow: (index, amount, physicalRows, source) => {
          // console.log('index :>> ', index)
          this.$store.dispatch(
            'createWaybill/changeInvoiceInfo',
            this.invoiceInfoData
          )
          if (this.invoiceInfoData.oldTableData[index]) {
            this.delPackingData(this.invoiceInfoData.oldTableData[index])
          }
        },
        /**
         * [复制到表格后触发]
         * @param  {[array]} data   [复制的值]
         * @param  {[array]} coords [复制的目标区域坐标]
         */
        afterPaste: (data, coords) => {
          const oldTableData = this.invoiceInfoData.oldTableData
          // console.log('oldTableData :>> ', oldTableData)
          // return
          const cols = [2, 12]
          let prop = ''
          for (
            let index = coords[0].startCol;
            index <= coords[0].endCol;
            index++
          ) {
            if (cols.includes(index)) {
              prop = index === 2 ? 'sku' : 'num'
            }
          }

          setTimeout(async() => {
            const table = this.invoiceInfoData.tableData
            // const t = this.$refs.hotTable
            for (
              let index = coords[0].startRow;
              index <= coords[0].endRow;
              index++
            ) {
              console.log('prop :>> ', prop)
              if (
                table[index].sku &&
                table[index].num &&
                prop &&
                table[index][prop] !== oldTableData[index][prop]
              ) {
                await this.afterChangeTable([
                  index,
                  prop,
                  oldTableData[index][prop],
                  table[index][prop]
                ])
              }
            }
          })
        }
      }
    }
  },
  watch: {
    'channelFormLeft.purposeWarehouseType': {
      handler(newVal, oldVal) {
        // console.log('newVal purposeWarehouseType:>> ', newVal)
        this.changeChannelForm()
      }
    },
    'channelFormLeft.countryId': {
      handler(newVal, oldVal) {
        // console.log('newVal purposeWarehouseType:>> ', newVal)
        this.changeDeclareValueCurrency()
      }
    },
    'invoiceInfoData.tableData': {
      handler(nVal) {
        console.log('nVal :>> ', nVal)
        this.$emit('update:invoiceTableInfo', this.invoiceInfoData)
      },
      immediate: true,
      deep: true
    },
    selectSku: {
      handler(nVal) {
        // console.log('selectSku nVal :>> ', nVal)
      }
    },
    multipleSelectionSku: {
      handler(nVal) {
        console.log('multipleSelectionSku nVal :>> ', nVal)
        if (nVal.length > 0) {
          const arr = []
          for (const i of nVal) {
            const t = clone(i)

            delete t.id
            delete t.declareValue
            if (!t.asin && t.salesConnection) {
              t.asin = t.salesConnection
            }
            if (t.customsCodeList && t.customsCodeList.length > 0) {
              t.customsClearanceCode = t.customsCodeList[0].hscode
              colHeaders[7] = `<span name="hscode">${
                this.publicData.customsCodeMap[
                  t.customsCodeList[0].customsCodeAreaManagementId
                ]
              }-清关编码</span>`
            }
            if (
              t.customsDeclaredPriceList &&
              t.customsDeclaredPriceList.length > 0
            ) {
              t.declareValue = t.customsDeclaredPriceList[0].price
            }

            delete t.customsCodeList
            delete t.customsDeclaredPriceList
            delete t.customsCodeListHtml
            delete t.customsDeclaredPriceListHtml
            arr.push(t)
          }

          const tableData = this.invoiceInfoData.tableData.filter(x =>
            checkRowsEmpty(x)
          )

          const target = arr.reduce(function(pre, cur, index, arr) {
            const target = pre.find(e => {
              return e.sku === cur.sku
            })
            // 判断是否存在相同sku数据
            if (!target) {
              pre.push(cur)
            }
            return pre
          }, tableData)

          if (target.length < 10) {
            const len = 10 - target.length
            for (let i = 0; i < len; i++) {
              target.push({})
            }
          }
          this.invoiceInfoData.tableData = target
        }
      }
    }
  },
  mounted() {
    this.skuUnit = Object.values(this.publicData.skuUnitMap)
  },
  beforeDestroy() {
    // 清除定时器
    clearInterval(this.timer)
    console.log('beforeDestroy')
  },
  destroyed() {
    // 清除定时器
    // clearInterval(this.timer);
    console.log('destroyed')
  },
  methods: {
    showSkuList() {
      this.showSkuListVisible = true
    },
    upLoadImg(type) {
      this.urlListIndex = type
      this.showUploadImg2 = true
    },
    checkTableData() {
      const tableData = this.invoiceInfoData.tableData.filter(x =>
        checkRowsEmpty(x)
      )

      if (tableData.length === 0) {
        this.$message.error('请填写发票数据！')
        return false
      }
      const isFBA = this.channelFormLeft.purposeWarehouseType === 100
      let text = ''
      for (const [i, e] of tableData.entries()) {
        if (isFBA && !e.shipmentId) {
          text += `<span class='margin-right-sm text-red'>请填写第${i +
            1}，shipmentId；<span>`
        }
        if (!e.sku) {
          text += `<span class='margin-right-sm text-red'>请填写第${i +
            1}行，sku；<span>`
        }
        if (!e.num) {
          text += `<span class='margin-right-sm text-red'>请填写第${i +
            1}行，sku个数；<span>`
        }
      }

      // this.showTips = text
      this.$emit('update:showTips', text)
    },
    clickBatch() {
      // if (!this.channelFormLeft.inStockChannel) {
      //   this.$message.error('请先选择渠道！')
      //   return
      // }
      this.fileList = []
      this.showUploadInvoice = true
    },
    getImgUrl(url) {
      // console.log('url :>> ', url)
      // console.log('this.coords.col :>> ', this.coords.col)
      const row = this.invoiceInfoData.tableData[this.coords.row]
      let n = 'imgUrl'
      switch (this.coords.col) {
        case 18:
          n = 'imgUrl'
          break
        case 21:
          n = 'imgUrl'
          break
        case 22:
          n = 'sellPriceScreenshot'
          break
        case 23:
          n = 'incomeScreenshot'
          break
      }
      this.$delete(row, n)
      // console.log('row :>> ', row)
      // console.log('n :>> ', n)
      this.$set(row, n, url)

      if (this.ruleForm.coverUrl) {
        const tbody = this.$refs.hotTable.$el.children[0].children[0]
          .children[0].children[0].children[0].children[2].children[
            this.coords.row
          ].children[this.coords.col + 1].children[0]

        tbody.src = globalData.fileUrl + url
      }
      this.$store.dispatch(
        'createWaybill/changeInvoiceInfo',
        clone(this.invoiceInfoData)
      )
      this.$emit('update:invoiceTableInfo', clone(this.invoiceInfoData))
    },
    // 批量上传图片数据 加入table
    getImgUrl2(data) {
      console.log('getImgUrl2 :>> ', data)
      for (const i of this.invoiceInfoData.tableData) {
        if (i.sku && data[i.sku]) {
          let key = ''
          switch (this.urlListIndex) {
            case 0:
              key = 'imgUrl'
              break
            case 1:
              key = 'sellPriceScreenshot'
              break
            case 2:
              key = 'incomeScreenshot'
              break
          }
          this.$delete(i, key)
          this.$set(i, key, data[i.sku])
        }
      }
      this.$store.dispatch(
        'createWaybill/changeInvoiceInfo',
        clone(this.invoiceInfoData)
      )
    },
    submitUpload() {
      this.$refs.upload.submit()
    },
    async uploadFn(params) {
      this.showLoading = true
      // console.log('params', params)
      // console.log('params', params.file.type)
      const isLt50M = params.file.size / 1024 / 1024 < 50

      if (!isLt50M) {
        this.$message.error('上传文件大小不能超过 50MB!')
        this.showLoading = false
        return false
      }
      const isEXCEL =
        params.file.type === 'application/vnd.ms-excel' ||
        params.file.type ===
          'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
      if (!isEXCEL) {
        this.$message.error('上传文件只能是EXCEL文件!')
        this.showLoading = false
        return false
      }
      // 通过 FormData 对象上传文件
      var formData = new FormData()
      formData.append('templateFile', params.file)
      formData.append('authorization', getToken())
      formData.append('countryId', this.channelFormLeft.countryId)
      formData.append(
        'purposeWarehouseType',
        this.channelFormLeft.purposeWarehouseType
      )

      const data = await doImportLiquidationPacking(formData)
      this.fileList = []
      if (data.error) {
        // this.$message.error(data.error)
        this.$message({
          type: 'error',
          dangerouslyUseHTMLString: true,
          message: data.error
        })
        this.showLoading = false
        return
      }
      if (data.declareValueCurrency) {
        // 同步发票

        const d = clone(data.liquidationInvoices)
        for (const i of d) {
          if (i.sellpriceScreenshot) {
            i.sellPriceScreenshot = i.sellpriceScreenshot
          }
        }
        if (!this.isJapan) {
          this.invoiceInfoData.declareValueCurrency = data.declareValueCurrency
        }

        this.invoiceInfoData.tableData = d
        this.invoiceInfoData.oldTableData = clone(d)
        this.$refs.hotTable.hotInstance.loadData(d)
        this.$store.dispatch(
          'createWaybill/changeInvoiceInfo',
          clone(this.invoiceInfoData)
        )
        this.$emit('update:invoiceTableInfo', clone(this.invoiceInfoData))
        // 同步箱单
        if (this.createTpye !== 'OrderToExpressDelivery') {
          if (data.packingListmMap) {
            // 存在箱单信息
            // console.log('上传信息存在箱单信息')
            this.IntegratePackingData(
              data.packingListmMap,
              'changeCustomerTotalPackages'
            )
          } else {
            // 不存在箱单信息 根据发票生成
            // console.log('上传信息不存在箱单信息')
            this.IntegrateInvoiceData()
          }
          // this.$store.dispatch(
          //   'createWaybill/changePackingInfo',
          //   clone(this.invoiceInfoData.tableData)
          // )
        }
        this.$message({
          message: '导入成功！',
          type: 'success'
        })

        this.showUploadInvoice = false
      } else {
        this.$message({
          type: 'error',
          dangerouslyUseHTMLString: true,
          message: data.error
        })
      }
      this.showLoading = false
    },

    afterChangeTable(changes) {
      console.log('changes :>> ', changes)
      // 解构赋值
      const [row, prop, oldValue, newValue] = changes
      const data = this.invoiceInfoData.tableData
      // const oldData = this.invoiceInfoData.oldTableData

      // sku 填入
      if (prop === 'sku' && this.selectSkuList.length > 0) {
        for (const i of this.selectSkuList) {
          if (i.sku === newValue) {
            const t = clone(i)
            delete t.id
            delete t.declareValue
            if (!t.asin && t.salesConnection) {
              t.asin = t.salesConnection
            }
            if (t.customsCodeList && t.customsCodeList.length > 0) {
              t.customsClearanceCode = t.customsCodeList[0].hscode
              colHeaders[7] = `<span name="hscode">${
                this.publicData.customsCodeMap[
                  t.customsCodeList[0].customsCodeAreaManagementId
                ]
              }-清关编码</span>`
            }
            if (
              t.customsDeclaredPriceList &&
              t.customsDeclaredPriceList.length > 0
            ) {
              t.declareValue = t.customsDeclaredPriceList[0].price
            }

            delete t.customsCodeList
            delete t.customsDeclaredPriceList

            const s = Object.assign(data[row], t)

            this.$set(this.invoiceInfoData.tableData, row, s)
            this.$set(this.invoiceInfoData.tableData[row], 'num', '')
          }
        }
      }

      const props = ['sku', 'num', 'shipmentId']
      const props2 = ['declareNameCn', 'declareNameEn']

      // 判断修改的值
      if (oldValue !== newValue && props.includes(prop)) {
        // 存在SKU 数量，修改
        if (data[row].sku && data[row].num) {
          this.changeHandsontable({ row, prop, oldValue, newValue })
        }
      }
      // 判断修改的值
      if (
        data[row].sku &&
        data[row].num &&
        oldValue !== newValue &&
        props2.includes(prop)
      ) {
        console.log('修改商品中英文名称 :>> ')
        this.changeGoodsName({ row, prop, oldValue, newValue })
      }
      this.$store.dispatch(
        'createWaybill/changeInvoiceInfo',
        this.invoiceInfoData
      )
      this.$emit('update:invoiceTableInfo', clone(this.invoiceInfoData))
    },
    async delPackingData(row) {
      console.log('删除数据 :>> ', row)
      console.log('this.invoiceInfoData :>> ', this.invoiceInfoData)
      const s = this.invoiceInfoData.tableData.find(
        x => x.shipmentId === row.shipmentId
      )
      const packingInfo = await clone(this.packingInfo)
      if (s) {
        console.log('部分删 :>> ')
        const target = packingInfo.find(x => x.shipmentId === row.shipmentId)
        console.log('target :>> ', target)
        if (!target) return

        for (let index = target.filterData.length - 1; index >= 0; index--) {
          if (target.filterData[index].skuName === row.sku) {
            target.filterData.splice(index, 1)
          }
        }
        for (let index = target.tableData.length - 1; index >= 0; index--) {
          if (target.tableData[index].skuName === row.sku) {
            target.tableData.splice(index, 1)
          }
        }
        if (target.tableData.length > 0) {
          await getSpanArr(target)
        }
      } else {
        console.log('全删 :>> ')
        const index = packingInfo.findIndex(
          x => x.shipmentId === row.shipmentId
        )
        if (index > -1) {
          packingInfo.splice(index, 1)
        }
      }

      this.invoiceInfoData.oldPackingInfo = packingInfo
      // 同步更新
      if (this.createTpye !== 'OrderToExpressDelivery') {
        this.$store.dispatch('createWaybill/changePackingInfo', packingInfo)
      }

      this.invoiceInfoData.oldTableData = await clone(
        this.invoiceInfoData.tableData
      )
      this.$store.dispatch(
        'createWaybill/changeInvoiceInfo',
        this.invoiceInfoData
      )
      this.$emit('update:invoiceTableInfo', clone(this.invoiceInfoData))
    },

    // 改变sku中英文
    changeGoodsName({ row, prop, oldValue, newValue }) {
      const target = this.packingInfo.find(
        x => x.shipmentId === this.invoiceInfoData.tableData[row].shipmentId
      )
      if (target) {
        for (const i of target.filterData) {
          if (
            i[prop] === oldValue &&
            i.skuName === this.invoiceInfoData.tableData[row].sku
          ) {
            this.$set(i, prop, newValue)
          }
        }
        for (const i of target.tableData) {
          if (
            i[prop] === oldValue &&
            i.skuName === this.invoiceInfoData.tableData[row].sku
          ) {
            this.$set(i, prop, newValue)
          }
        }
        console.log('target :>> ', target)
      }
    },

    // 整合数据
    IntegrateData() {
      const isFBA = this.channelFormLeft.purposeWarehouseType === 100
      // 新数据
      const newArr = []

      this.invoiceInfoData.tableData.forEach((j, index) => {
        if (isNoEmptyObject(j) && j.sku && j.num) {
          j.shipmentId = j.shipmentId ? j.shipmentId.trim() : ''
          const obj = {
            shipmentId: j.shipmentId,
            filterData: [
              {
                skuName: j.sku,
                declareNameCn: j.declareNameCn || '',
                declareNameEn: j.declareNameEn || '',
                skuNum: j.num,
                packingNum: '0',
                inputNum: '0'
              }
            ],
            startBoxNo: null,
            endBoxNo: null,
            show: true,
            oldRule: 'U000001', // 箱规旧值
            rule: 'U000001', // 默认箱规
            grossWeight: '', // 毛重
            length: '',
            width: '',
            height: '',
            tableData: [],
            spanArr: [],
            pos: 0
          }
          newArr.push(obj)
        }
      })

      if (newArr.length === 0) return []

      const newArray = isFBA ? newArr.filter(i => i.shipmentId !== '') : newArr

      //
      const filteredData = newArray.reduce((acc, cur, index, arr) => {
        const target = acc.find(e => {
          return e.shipmentId === cur.shipmentId
        })
        // 判断是否存在相同shipmentId数据
        if (target) {
          cur.filterData.reduce((pVal, cVal) => {
            const target1 = pVal.find(x => x.skuName === cVal.skuName)
            if (target1) {
              // 相同sku 合并数量
              target1.skuNum += parseInt(cVal.skuNum)
            } else {
              pVal.push(cVal)
            }
            return pVal
          }, target.filterData)
        } else {
          acc.push(cur)
        }

        return acc
      }, [])

      return filteredData
    },
    /**
     * @description: 根据表单生成对应箱单
     * @param {Number} row 数据第几行
     * @param {String} prop 参数名
     * @param {*} oldValue 该参数名 旧数据
     * @param {*} newValue 该参数名 新数据
     * @param {Boolean} changeFba 改变仓库类型
     */
    async changeHandsontable({
      row,
      prop,
      oldValue,
      newValue,
      changeFba = false
    }) {
      /** 直接修改表格
       * 1.发票表格修改shipment ID ,判断是否已存在该行数据
       * 2.存在该行数据，保持其他数据，修改该数据
       * 3.不存在该行数据，并且满足生成条件，生成数据
       * 4.判断条件  oldValue === undefined && props.includes(prop)
       */
      console.log('修改表格 :>> ', '修改表格')
      const isFBA = this.channelFormLeft.purposeWarehouseType === 100
      const filteredData = await this.IntegrateData()
      console.log(
        '%cchangeHandsontabl-filteredData: ',
        'color: #fff; background: #000;',
        filteredData
      )
      // return
      const props = ['sku', 'num']
      const params = {
        filteredData,
        row,
        prop
      }
      // console.log('this.invoiceInfoData 401 :>> ', this.invoiceInfoData)
      // console.log('oldValue :>> ', oldValue)
      // 满足 shipmentId sku num 并且其中一项之前为空 => 新增数据
      if (isFBA) {
        props.push('shipmentId')
      }
      if (prop && props.includes(prop) && !oldValue && newValue) {
        this.increasePackingData(params)
      } else {
        this.changePackingData(params)
      }
    },
    // 新增数据
    async increasePackingData(params) {
      console.log('新增数据', params)
      const oldData = this.invoiceInfoData.oldPackingInfo

      // console.log('oldData :>> ', oldData)
      let packingInfo = []
      const filteredData = clone(params.filteredData)

      // 将旧值 还原
      oldData.reduce((pVal, cVal) => {
        const targetShipmentId = pVal.find(
          x => x.shipmentId === cVal.shipmentId
        )
        if (targetShipmentId) {
          cVal.filterData.reduce((pVal, cVal) => {
            const target1 = pVal.find(x => x.skuName === cVal.skuName)
            if (target1) {
              // 接收已装箱值，其他不改变
              target1.packingNum = cVal.packingNum
            } else {
              pVal.push(cVal)
            }
            return pVal
          }, targetShipmentId.filterData)

          Object.assign(targetShipmentId, {
            spanArr: cVal.spanArr,
            tableData: cVal.tableData,
            rule: cVal.rule
          })
        } else {
          pVal.push(cVal)
        }
        return pVal
      }, filteredData)
      packingInfo = await clone(filteredData)
      console.log('packingInfo :>> ', packingInfo)
      this.invoiceInfoData.oldPackingInfo = packingInfo
      // 同步更新
      if (this.createTpye !== 'OrderToExpressDelivery') {
        this.$store.dispatch('createWaybill/changePackingInfo', packingInfo)
      }

      this.invoiceInfoData.oldTableData = await clone(
        this.invoiceInfoData.tableData
      )
      this.$store.dispatch(
        'createWaybill/changeInvoiceInfo',
        this.invoiceInfoData
      )
      this.$emit('update:invoiceTableInfo', clone(this.invoiceInfoData))
    },
    // 修改数据
    async changePackingData(params) {
      console.log('修改数据', params)
      let filteredData = clone(params.filteredData)
      let packingInfo = []
      const oldData = this.invoiceInfoData.oldPackingInfo
      console.log('修改数据 oldData :>> ', oldData)
      // 旧数据为空
      if (oldData.length === 0) {
        console.log('旧数据为空')
        this.increasePackingData(params)
        return
      }
      console.log(
        'this.invoiceInfoData.oldTableData:>> ',
        this.invoiceInfoData.oldTableData
      )
      console.log(
        'this.invoiceInfoData.oldTableData[params.row].shipmentId :>> ',
        this.invoiceInfoData.oldTableData[params.row]
      )
      const oldTarget = oldData.find(
        i =>
          i.shipmentId ===
          this.invoiceInfoData.oldTableData[params.row].shipmentId
      )

      let newTarget = filteredData.find(
        i =>
          i.shipmentId === this.invoiceInfoData.tableData[params.row].shipmentId
      )
      // 获取目标下标
      const index = filteredData
        .map(item => item.shipmentId)
        .indexOf(this.invoiceInfoData.tableData[params.row].shipmentId)

      const oldSid = oldTarget.shipmentId || ''
      // console.log('oldSid :>> ', oldSid)
      // console.log('changePackingData -newTarget', newTarget)
      const oldSkuName = this.invoiceInfoData.oldTableData[params.row]
        ? this.invoiceInfoData.oldTableData[params.row].sku
        : ''
      const newSkuName = this.invoiceInfoData.tableData[params.row]
        ? this.invoiceInfoData.tableData[params.row].sku
        : ''
      // 修改shipmentID 且旧数据存在修改后的id
      if (params.prop === 'shipmentId') {
        filteredData = await this.changeShipmentID({
          oldSid,
          newTarget,
          oldTarget,
          oldSkuName,
          oldData,
          filteredData: filteredData
        })

        // 还原非修改目标数据
        for (const [i, e] of filteredData.entries()) {
          if (
            e.shipmentId !== oldSid &&
            e.shipmentId !== newTarget.shipmentId
          ) {
            const t = oldData.find(x => x.shipmentId === e.shipmentId)
            if (t) {
              filteredData.splice(i, 1, t)
            }
          }
        }
      } else {
        // 非 shipmentID  修改
        if (params.prop === 'sku') {
          newTarget = await this.changeSkuName({
            newTarget,
            oldTarget,
            oldSkuName,
            row: params.row,
            newSkuName,
            oldData
          })
        } else if (params.prop === 'num') {
          await this.changePackingNum(
            oldTarget.filterData,
            newTarget.filterData
          )
          newTarget.spanArr = oldTarget.spanArr
          newTarget.tableData = oldTarget.tableData
          newTarget.rule = oldTarget.rule
        } else if (params.prop === 'declareNameCn') {
          // 修改商品中文名
          const oldName = this.invoiceInfoData.oldTableData[params.row]
            .declareNameCn
          const name = this.invoiceInfoData.tableData[params.row].declareNameCn
          for (const i of oldTarget.filterData) {
            if (
              oldName &&
              i.declareNameCn === oldName &&
              i.skuName === newSkuName
            ) {
              i.declareNameCn = name
            } else if (i.skuName === newSkuName) {
              i.declareNameCn = name
            }
          }

          for (const i of oldTarget.tableData) {
            if (
              oldName &&
              i.declareNameCn === oldName &&
              i.skuName === newSkuName
            ) {
              i.declareNameCn = name
            } else if (i.skuName === newSkuName) {
              i.declareNameCn = name
            }
          }

          newTarget.filterData = oldTarget.filterData
          newTarget.tableData = oldTarget.tableData
        } else {
          newTarget = oldTarget
        }

        // 还原非修改目标数据
        for (const [i, e] of filteredData.entries()) {
          if (e.shipmentId !== oldSid) {
            const t = oldData.find(x => x.shipmentId === e.shipmentId)
            if (t) {
              console.log('t :>> ', t)
              filteredData.splice(i, 1, t)
            }
          }
        }
      }
      // console.log('params.filteredData :>> ', filteredData)
      // console.log('newTarget :>> ', newTarget)
      let obj = newTarget
      // console.log('ewTarget.tableData :>> ', newTarget.tableData)
      if (newTarget.tableData.length > 0) {
        obj = await getSpanArr(newTarget)
      }

      filteredData.splice(index, 1, obj)

      packingInfo = filteredData

      console.log(
        '%c 修改数据-packingInfo: ',
        'color: MidnightBlue; background: Aquamarine;',
        filteredData
      )

      this.invoiceInfoData.oldPackingInfo = await clone(packingInfo)
      // 同步更新
      if (this.createTpye !== 'OrderToExpressDelivery') {
        this.$store.dispatch('createWaybill/changePackingInfo', packingInfo)
      }

      this.invoiceInfoData.oldTableData = await clone(
        this.invoiceInfoData.tableData
      )
      this.$store.dispatch(
        'createWaybill/changeInvoiceInfo',
        this.invoiceInfoData
      )
      this.$emit('update:invoiceTableInfo', clone(this.invoiceInfoData))
    },
    resetPacking() {
      const tableData = this.invoiceInfoData.tableData.filter(x =>
        checkRowsEmpty(x)
      )

      if (tableData.length === 0) {
        this.$message.error('请填写发票数据！')
        return false
      }
      const isFBA = this.channelFormLeft.purposeWarehouseType === 100

      for (const [i, e] of tableData.entries()) {
        if (isFBA && !e.shipmentId) {
          this.$message.error(`请填写发票数据第${i + 1}，shipmentId`)
          return
        }
        if (!e.sku) {
          this.$message.error(`请填写发票数据第${i + 1}行，sku`)
          return
        }
        if (!e.num) {
          this.$message.error(`请填写发票数据第${i + 1}行，sku个数`)
          return
        }
      }

      this.invoiceInfoData.oldPackingInfo = []
      this.IntegrateInvoiceData()
    },

    // 通过上传文件导入的发票数据
    async IntegrateInvoiceData() {
      const filteredData = await this.IntegrateData()

      const params = {
        filteredData
      }
      if (filteredData.length === 0) {
        // 发票数据为空
        this.$store.dispatch('createWaybill/changePackingInfo', [])
      } else {
        this.increasePackingData(params)
      }
    },

    // 处理返回的数组
    async processingArrInfo(data) {
      const packingInfo = []
      const isVip = this.name.indexOf('通网供应链') > -1
      for (const i of data) {
        // console.log('i :>> ', i)
        const obj = {
          shipmentId:
            i.startNumNo.slice(0, i.startNumNo.lastIndexOf('U')) || '',
          tableData: [],
          show: true
        }
        // for (const j of data[i]) {
        const l = i.startNumNo.slice(i.startNumNo.lastIndexOf('U')).length
        // console.log('l :>> ', l)
        switch (l) {
          case 4:
            obj.rule = 'U001'
            break
          case 5:
            obj.rule = 'U0001'
            break
          case 6:
            obj.rule = 'U00001'
            break
          case 7:
            obj.rule = 'U000001'
            break
          default:
            obj.rule = 'U0001'
            break
        }
        if (i.packSkuList.length > 0) {
          for (const k of i.packSkuList) {
            obj.tableData.push({
              cartonNo: i.startNumNo,
              declareNameCn: k.declareNameCn,
              declareNameEn: k.declareNameEn,
              grossWeight: i.weight,
              height: i.height,
              length: i.length,
              shipmentId:
                data[0].startNumNo.slice(
                  0,
                  data[0].startNumNo.lastIndexOf('U')
                ) || '',
              skuName: k.sku,
              skuNum: k.num,
              width: i.width
            })
          }
        } else {
          obj.tableData.push({
            cartonNo: i.startNumNo,
            declareNameCn: '',
            grossWeight: i.weight,
            height: i.height,
            length: i.length,
            shipmentId: i.shipmentId || '',
            skuName: '',
            skuNum: '',
            width: i.width
          })
        }
        packingInfo.push(obj)
      }

      const d = packingInfo.reduce((pVal, cVal) => {
        const target = pVal.find(x => x.shipmentId === cVal.shipmentId)
        if (target) {
          // 接收已装箱值，其他不改变
          target.tableData = [...target.tableData, ...cVal.tableData]
        } else {
          pVal.push(cVal)
        }
        return pVal
      }, [])

      console.log('d :>> ', d)

      for (const i of d) {
        if (i.tableData.length > 0) {
          await getSpanArr(i, isVip)
        }
      }

      console.log('packingInfo :>> ', d)
      // console.log('packingInfo :>> ', packingInfo)
      return d
    },
    // 处理返回的对象
    async processingObjInfo(data) {
      const isVip = this.name.indexOf('通网供应链') > -1
      const packingInfo = []
      for (const i in data) {
        // console.log('i :>> ', i)
        const obj = {
          shipmentId: i,
          tableData: [],
          show: true
        }
        for (const j of data[i]) {
          const l = j.startNumNo.slice(j.startNumNo.lastIndexOf('U')).length
          switch (l) {
            case 4:
              obj.rule = 'U001'
              break
            case 5:
              obj.rule = 'U0001'
              break
            case 6:
              obj.rule = 'U00001'
              break
            case 7:
              obj.rule = 'U000001'
              break
          }

          for (const k of j.packSkuList) {
            obj.tableData.push({
              cartonNo: j.startNumNo,
              declareNameCn: k.declareNameCn,
              declareNameEn: k.declareNameEn,
              grossWeight: j.weight,
              height: j.height,
              length: j.length,
              shipmentId: i,
              skuName: k.sku ? k.sku.trim() : k.sku,
              skuNum: k.num,
              width: j.width,
              remark: j.remark || ''
            })
          }
        }
        await getSpanArr(obj, isVip)
        packingInfo.push(obj)
      }
      return packingInfo
    },

    // 通过上传文件导入的箱单数据
    async IntegratePackingData(data, type) {
      // console.log('IntegratePackingData data :>> ', data)
      let packingInfo = []
      if (Object.prototype.toString.call(data) === '[object Array]') {
        packingInfo = await this.processingArrInfo(data)
      } else if (Object.prototype.toString.call(data) === '[object Object]') {
        console.log('value是对象')
        packingInfo = await this.processingObjInfo(data)
      }

      console.log('packingInfo :>> ', packingInfo)
      const filteredData = await this.IntegrateData()
      // 赋值 filteredData
      console.log('filteredData :>> ', filteredData)
      for (const i of filteredData) {
        for (const j of packingInfo) {
          if (i.shipmentId === j.shipmentId) {
            j.filterData = i.filterData
            console.log('j :>> ', j)
            for (const k of j.filterData) {
              let num = 0
              for (const u of j.tableData) {
                // console.log('u.skuName :>>', u.skuName)
                // console.log('k.skuName :>>', k.skuName)
                console.log(
                  `${u.skuName} === ${k.skuName} :>> `,
                  u.skuName === k.skuName
                )
                if (u.skuName === k.skuName) {
                  num += parseInt(u.skuNum)
                  // console.log('packingNum num :>> ', num)
                }
              }
              k.packingNum = num
            }
          }
        }
      }

      if (type) {
        // 箱单信息
        const plist = []

        for (const i of packingInfo) {
          for (const j of i.tableData) {
            plist.push(j.cartonNo)
          }
        }

        const packingList = plist.reduce((pVal, cVal) => {
          const target = pVal.find(x => x === cVal)
          if (!target) {
            pVal.push(cVal)
          }
          return pVal
        }, [])
        this.$parent.$refs.selectChannelLeftComp.channelform.customerTotalPackages =
          packingList.length
      }
      this.invoiceInfoData.oldPackingInfo = clone(packingInfo)

      this.$store.dispatch('createWaybill/changePackingInfo', packingInfo)
    },
    /**
     * @description:
     * @param {*} oldSid 修改前的sid
     * @param {*} newTarget 修改后的目标数据
     * @param {*} oldTarget 修改前的目标数据
     * @param {*} oldSkuName 修改前的sku
     * @param {*} oldData 修改前的装箱单数据
     * @param {*} filteredData
     * @return {*}
     */
    async changeShipmentID({
      oldSid,
      newTarget,
      oldTarget,
      oldSkuName,
      oldData,
      filteredData
    }) {
      // 获取 旧SID 在修改前Table数据列表
      const oldSidList = this.invoiceInfoData.oldTableData.filter(
        i => i.shipmentId === oldTarget.shipmentId
      )

      // 获取新SID 在修改前Table数据列表

      const newSidList = this.invoiceInfoData.oldTableData.filter(
        i => i.shipmentId === newTarget.shipmentId
      )

      // 旧shipmentId的packing 数据
      const oldPacking_oldSid = oldData.find(i => i.shipmentId === oldSid)
      const oldPacking_newSid = oldData.find(
        i => i.shipmentId === newTarget.shipmentId
      )

      // 新数据
      const newPacking_oldSid = filteredData.find(i => i.shipmentId === oldSid)
      const newPacking_newSid = filteredData.find(
        i => i.shipmentId === newTarget.shipmentId
      )

      // 大于1 && 大于0,证明改之前存在同shipmentID 数据/
      if (oldSidList.length > 1 && newSidList.length > 0) {
        console.log(
          '-----------修改前存在新SID数据，修改后存在旧SID数据----------'
        )
        // TODO 区分 相同shipmentID，相同skuName 的已装箱tableData 的分离
        newPacking_oldSid.tableData.push(
          ...oldPacking_oldSid.tableData.filter(i => i.skuName !== oldSkuName)
        )
        newPacking_oldSid.rule = oldPacking_oldSid.rule

        await this.changePackingNum(
          oldPacking_newSid.filterData,
          await this.changePackingNum(
            oldPacking_oldSid.filterData,
            newPacking_oldSid.filterData
          )
        )
        await this.changePackingNum(
          oldPacking_oldSid.filterData,
          newPacking_newSid.filterData
        )
        const t = oldPacking_oldSid.tableData.filter(
          i => i.skuName === oldSkuName
        )
        for (const j of t) {
          j.shipmentId = newTarget.shipmentId
          j.cartonNo =
            newTarget.shipmentId + j.cartonNo.slice(j.cartonNo.lastIndexOf('U'))
        }
        // 原有的数据，+ 新增的数据
        newPacking_newSid.tableData.push(...oldPacking_newSid.tableData, ...t)
        newPacking_newSid.rule = oldPacking_newSid.rule
        await this.changePackingNum(
          oldPacking_newSid.filterData,
          newPacking_newSid.filterData
        )
      } else if (oldSidList.length > 1 && newSidList.length === 0) {
        console.log(
          '-----------修改前不存在新SID数据，修改后存在旧SID数据-------------'
        )

        await this.changePackingNum(
          oldPacking_oldSid.filterData,
          newPacking_oldSid.filterData
        )
        newPacking_oldSid.rule = oldPacking_oldSid.rule
        newPacking_oldSid.tableData = oldTarget.tableData.filter(
          x => x.skuName !== oldSkuName
        )
        newPacking_oldSid.filterData = oldTarget.filterData.filter(
          x => x.skuName !== oldSkuName
        )

        const t = oldPacking_oldSid.tableData.filter(
          i => i.skuName === oldSkuName
        )
        for (const j of t) {
          j.shipmentId = newTarget.shipmentId
          j.cartonNo =
            newTarget.shipmentId + j.cartonNo.slice(j.cartonNo.lastIndexOf('U'))
        }
        newTarget.tableData.push(...t)
        await this.changePackingNum(
          oldPacking_oldSid.filterData,
          newTarget.filterData
        )
        console.log('newTarget :>> ', newTarget)
      } else if (oldSidList.length === 1 && newSidList.length > 0) {
        console.log(
          '------------修改前存在新SID数据，修改后不存在旧SID数据------------'
        )
        // 旧数据没有其他相同shipmentID数据，有修改后shipmentID数据
        // 原有的数据，+ 新增的数据
        const t = oldPacking_oldSid.tableData
        for (const j of t) {
          j.shipmentId = newTarget.shipmentId
          j.cartonNo =
            newTarget.shipmentId + j.cartonNo.slice(j.cartonNo.lastIndexOf('U'))
        }

        newPacking_newSid.tableData.push(...oldPacking_newSid.tableData, ...t)
        newPacking_newSid.rule = oldPacking_newSid.rule

        //
        await this.changePackingNum(
          oldPacking_newSid.filterData,
          await this.changePackingNum(
            oldPacking_oldSid.filterData,
            newPacking_newSid.filterData
          )
        )
      } else if (oldSidList.length === 1 && newSidList.length === 0) {
        console.log(
          '------------修改前不存在新SID数据，修改后不存在旧SID数据-------------'
        )
        // 旧数据没有其他相同shipmentID数据，且没有有修改后shipmentID数据
        const t = oldPacking_oldSid.tableData
        for (const j of t) {
          j.shipmentId = newTarget.shipmentId
          j.cartonNo =
            newTarget.shipmentId + j.cartonNo.slice(j.cartonNo.lastIndexOf('U'))
        }
        newTarget.tableData.push(...t)
        await this.changePackingNum(
          oldPacking_oldSid.filterData,
          newTarget.filterData
        )
      }
      // console.log('newPacking_newSid :>> ', newPacking_newSid)
      // console.log('newPacking_oldSid :>> ', newPacking_oldSid)
      newPacking_newSid.tableData = this.deduplication(
        newPacking_newSid.tableData
      )
      if (newPacking_oldSid) {
        newPacking_oldSid.tableData = this.deduplication(
          newPacking_oldSid.tableData
        )
        await getSpanArr(newPacking_oldSid)
      }

      return filteredData
    },
    async changeSkuName(params) {
      /**
       * 修改skuName
       * 1.判断修改前的skuName与修改后的skuName ,同shipmentID 中除了自身之外是否存在相同skuName
       * 2.改前无，改后无   转移数据
       * 3.改前无，改后有   转移，合并数据
       * 4.改前有，改后无   转移，分离数据
       * 5.改前有，改后有   转移，合并数据
       */
      const {
        newTarget,
        oldTarget,
        oldSkuName,
        row,
        newSkuName,
        oldData
      } = params
      const repeatList = []
      this.invoiceInfoData.oldTableData.forEach((e, i) => {
        if (i !== row && e.shipmentId === oldTarget.shipmentId) {
          repeatList.push(e)
        }
      })

      console.log('repeatList', repeatList)

      const beforeName = repeatList.find(x => x.sku === oldSkuName)
      const afterName = repeatList.find(x => x.sku === newSkuName)
      console.log(
        '%cbeforeName: ',
        'color: #fff; background: pink;',
        beforeName
      )

      if (!beforeName && !afterName) {
        // TODO
        console.log('newSkuName :>> ', newSkuName)
        // 改前无，改后无   转移数据
        for (const i of oldTarget.filterData) {
          if (i.skuName === oldSkuName) {
            i.skuName = newSkuName
          }
        }
        for (const i of oldTarget.tableData) {
          if (i.skuName === oldSkuName) {
            i.skuName = newSkuName
          }
        }

        newTarget.filterData = oldTarget.filterData
        newTarget.spanArr = oldTarget.spanArr
        newTarget.tableData = oldTarget.tableData
      } else if (!beforeName && afterName) {
        // 改前无，改后有   转移，合并数据
        console.log('改前无，改后有   转移，合并数据 :>> ')
        const targetPacking = oldData.find(
          i => i.shipmentId === afterName.shipmentId
        )

        if (targetPacking.tableData.length === 0) return newTarget
        console.log('targetPacking :>> ', targetPacking)

        const oldSku = this.invoiceInfoData.oldTableData[row].sku
        const sku = this.invoiceInfoData.tableData[row].sku
        for (const i of targetPacking.filterData) {
          if (oldSku && i.skuName === oldSku) {
            i.skuName = sku
          } else {
            i.skuName = sku
          }
        }

        for (const i of targetPacking.tableData) {
          if (oldSku && i.skuName === oldSku) {
            i.skuName = sku
          } else {
            i.skuName = sku
          }
        }
        newTarget.filterData = await this.changePackingNum(
          targetPacking.filterData,
          newTarget.filterData
        )

        newTarget.spanArr = targetPacking.spanArr
        newTarget.tableData = this.deduplication(targetPacking.tableData)
      } else if (beforeName && !afterName) {
        // TODO
        console.log('改前有，改后无    转移，合并数据 :>> ')
        // 改前有，改后无   转移，分离数据
      } else if (beforeName && afterName) {
        // TODO
        console.log('改前有，改后有   转移，合并数据 :>> ')
        // 改前有，改后有   转移，合并数据
      }

      return newTarget
    },

    // 重复数据相加
    deduplication(data) {
      const d = data.reduce((pVal, cVal) => {
        const target = pVal.find(
          x =>
            x.cartonNo === cVal.cartonNo &&
            x.skuName === cVal.skuName &&
            x.declareNameCn === cVal.declareNameCn
        )
        if (target) {
          console.log('target.skuNum :>> ', target.skuNum)
          console.log('cVal.skuNum :>> ', cVal.skuNum)
          // 接收已装箱值，其他不改变
          target.skuNum += cVal.skuNum
        } else {
          pVal.push(cVal)
        }
        return pVal
      }, [])

      return d
    },

    // 检查已装数量
    changePackingNum(data, data2) {
      data.reduce((pVal, cVal) => {
        const target = pVal.find(x => x.skuName === cVal.skuName)
        if (target) {
          console.log('changePackingNum target :>> ', target)
          // 接收已装箱值，其他不改变
          target.packingNum =
            parseInt(cVal.packingNum) + parseInt(target.packingNum)
        }
        return pVal
      }, data2)
      return data2
    },

    findSku(data, name) {
      const flag = data.filterData.find(x => x.skuName === name)
      return !!flag
    },
    checkSku(row, data) {
      const list = []
      data.forEach((i, index) => {
        if (i[0] === data[row][0] && i[2] === data[row][2]) {
          list.push({
            index
          })
        }
      })

      return list
    },

    setHeader() {
      let headerList = []
      if (this.channelFormLeft.purposeWarehouseType === 100) {
        headerList = [...fbaHead]
      } else {
        headerList = [...noFbaHead]
      }
      if (this.isJapan) {
        headerList = [...headerList, ...colHeaders, ...JapanLineHeader]
      } else {
        headerList = [...headerList, ...colHeaders, ...otherHeader]
      }
      return headerList
    },
    // 改变目的仓库
    changeChannelForm() {
      if (this.channelFormLeft.purposeWarehouseType === 100) {
        this.$refs.hotTable.hotInstance.updateSettings(this.hotSettings)
      }
    },
    hasClass(elem, cls) {
      cls = cls || ''
      if (cls.replace(/\s/g, '').length === 0) return false // 当cls没有参数时，返回false
      return new RegExp(' ' + cls + ' ').test(' ' + elem.className + ' ')
    },
    resetInvoice() {
      this.$set(this.invoiceInfoData, 'tableData', [
        {},
        {},
        {},
        {},
        {},
        {},
        {},
        {},
        {},
        {},
        {}
      ])

      this.$set(this.invoiceInfoData, 'oldPackingInfo', [])
      this.$set(this.invoiceInfoData, 'oldTableData', [])
      this.$set(this.invoiceInfoData, 'declareValueCurrency', '')
      // 同步更新
      if (this.createTpye !== 'OrderToExpressDelivery') {
        this.$store.dispatch('createWaybill/changePackingInfo', [])
      }
    },

    handleClose(done) {
      this.$confirm('确认关闭？')
        .then(_ => {
          done()
        })
        .catch(_ => {})
    },

    addEmptyData() {
      this.invoiceInfoData.tableData.push({})
    },
    cancelChangeImg() {
      this.ruleForm.coverUrl = ''
      this.showUploadImg = false
    },
    enterImg() {
      this.showUploadImg = false
      // console.log(this.coords)
      // console.log(
      //   this.invoiceInfoData.tableData[this.coords.row][this.coords.col]
      // )
      this.invoiceInfoData.tableData[this.coords.row][
        this.coords.col
      ] = this.ruleForm.coverUrl
      this.ruleForm.coverUrl = ''
    },
    // 恢复数据
    restoreInvoiceData() {
      this.$confirm(
        '该功能只能恢复当前电脑的最近一次发票数据, 是否继续?',
        '恢复发票内容',
        {
          confirmButtonText: '确定',
          cancelButtonText: '取消',
          type: 'warning'
        }
      ).then(() => {
        let str = ''
        if (this.waybillId) {
          console.log('this.waybillId :>> ', this.waybillId)
          str = this.waybillId
        } else {
          console.log('this.waybillCode :>> ', this.waybillCode)
          str = this.waybillCode
        }

        if (sessionStorage.getItem(`tableInvoice-${str}`)) {
          this.invoiceInfoData.tableData = JSON.parse(
            sessionStorage.getItem(`tableInvoice-${str}`)
          )
          console.log(JSON.parse(sessionStorage.getItem(`tableInvoice-${str}`)))
          this.$message({
            type: 'success',
            message: '恢复成功!'
          })
          if (this.invoiceInfoData.tableData.length > 0) {
            this.IntegrateInvoiceData()
          }
        } else {
          this.$message('暂无数据')
        }
      })
    },
    imagePreview: function(file) {
      var self = this
      // 定义一个文件阅读器
      var reader = new FileReader()
      // 文件装载后将其显示在图片预览里
      reader.onload = function(e) {
        // 将bade64位图片保存至数组里供上面图片显示
        self.ruleForm.coverUrl = e.target.result
      }
      reader.readAsDataURL(file)
      // console.log(111)
    },
    // 根据国家修改币种
    changeDeclareValueCurrency() {
      const n = this.publicData.countryMap[this.channelFormLeft.countryId]

      if (!n) return
      const currencyMap = { USD: 'USD' }
      this.invoiceInfoData.declareValueCurrency = 'USD'
      if (n.indexOf('加拿大') > -1) {
        currencyMap['CAD'] = 'CAD'
      } else if (n.indexOf('英国') > -1) {
        currencyMap['GBP'] = 'GBP'
        currencyMap['EUR'] = 'EUR'
      } else if (n.indexOf('澳大利亚') > -1) {
        currencyMap['AUD'] = 'AUD'
      } else if (n.indexOf('新加坡') > -1) {
        currencyMap['SGD'] = 'SGD'
      } else if (
        n.indexOf('法国') > -1 ||
        n.indexOf('德国') > -1 ||
        n.indexOf('意大利') > -1 ||
        n.indexOf('西班牙') > -1
      ) {
        currencyMap['EUR'] = 'EUR'
      }

      if (n.indexOf('日本') > -1) {
        currencyMap['JPY'] = 'JPY'
        if (this.createTpye !== 'OrderToExpressDelivery') {
          delete currencyMap['USD']
          this.invoiceInfoData.declareValueCurrency = 'JPY'
        }
      }

      this.currencyMap = currencyMap
    },
    coverRenderer(instance, td, row, col, prop, value, cellProperties) {
      const escaped = Handsontable.helper.stringify(value)
      if (
        escaped.indexOf('http') === 0 ||
        escaped.lastIndexOf('.webp') > -1 ||
        escaped.lastIndexOf('.WEBP') > -1 ||
        escaped.lastIndexOf('.bmp') > -1 ||
        escaped.lastIndexOf('.BMP') > -1 ||
        escaped.lastIndexOf('.jpeg') > -1 ||
        escaped.lastIndexOf('.JPEG') > -1 ||
        escaped.lastIndexOf('.jpg') > -1 ||
        escaped.lastIndexOf('.png') > -1 ||
        escaped.lastIndexOf('.JPG') > -1 ||
        escaped.lastIndexOf('.PNG') > -1
      ) {
        const img = document.createElement('img')
        if (value.indexOf('http') > -1) {
          img.setAttribute('src', value)
        } else {
          img.setAttribute('src', globalData.fileUrl + value)
        }
        img.setAttribute('class', 'hasImg')
        img.onclick = params => {
          this.showUploadImg = true
          this.ruleForm.coverUrl = img.src
        }
        Handsontable.dom.addEvent(img, 'mousedown', function(event) {
          event.preventDefault()
        })

        Handsontable.dom.empty(td)
        td.appendChild(img)
        td.childNodes[0].style = 'width:50px;'
      } else {
        Handsontable.renderers.TextRenderer.apply(this, arguments)
        const d = document.createElement('span')
        d.innerHTML = '上传图片'

        d.onclick = params => {
          this.showUploadImg = true
        }
        td.setAttribute('class', 'td-center')
        td.appendChild(d)
      }

      return td
    },
    skuCellRenderer(instance, td, row, col, prop, value, cellProperties) {
      Handsontable.renderers.HtmlRenderer.apply(this, arguments)
      td.style.backgroundColor = '#fff'
      // removeClass(td, 'htInvalid')
      td.classList.remove('htInvalid')
    },
    buildColumns(isJP) {
      const _this = this
      let defaultColumns = [
        {
          data: 'shipmentId', // 指定所指列
          width: 100,
          allowEmpty: false,
          type: 'text' // 类型
        },
        {
          data: 'referenceId',
          allowEmpty: false,
          width: 90,
          type: 'text'
        },
        {
          data: 'sku',
          allowEmpty: false,
          width: 120,
          type: 'autocomplete',
          source: async function(query, process) {
            if (_this.timer2) {
              clearTimeout(_this.timer2)
            }
            _this.timer2 = setTimeout(() => {
              console.log('query :>> ', query)
              queryApiSkuInfos({
                currency: _this.invoiceInfoData.declareValueCurrency,
                countryId: _this.channelFormLeft.countryId,
                sku: query
              }).then(res => {
                const skuArrays = res // 检索后SKU信息集合
                console.log('skuArrays :>> ', skuArrays)
                if (skuArrays) {
                  _this.selectSkuList = skuArrays
                  const skuCollection = [] // 存储搜索后的SKU集合
                  // selectSku = skuArrays // 将SKU信息赋值给全局变量
                  for (let i = 0; i < skuArrays.length; i++) {
                    const sku = skuArrays[i].sku
                    if (sku) {
                      skuCollection.push(sku)
                    }
                  }
                  console.log('skuCollection :>> ', skuCollection)
                  process(skuCollection)
                }
              })
            }, 800)
          },
          strict: false
          // renderer: skuCellRenderer
        },

        {
          data: 'declareNameEn',
          // allowEmpty: false,
          width: 65,
          type: 'text',
          validator: function(v, callback) {
            const reg = new RegExp(
              '([\u4E00-\u9FFF]|[\u3002\uff1b\uff0c\uff1a\u201c\u201d\uff08\uff09\u3001\uff1f\u300a\u300b\uff01\u3010\u3011\uffe5])+',
              'g'
            )
            if (reg.test(v)) {
              callback(false)
              _this.$message.error('请勿包含中文字符')
            } else {
              callback(true)
            }
          }
        },
        {
          data: 'declareNameCn',
          allowEmpty: false,
          width: 65,
          type: 'text'
        },
        {
          data: 'brand',
          allowEmpty: false,
          width: 55,
          type: 'text'
        },
        {
          data: 'material',
          allowEmpty: false,
          width: 55,
          type: 'text'
        },
        {
          data: 'purpose',
          allowEmpty: false,
          width: 55,
          type: 'text'
        },
        {
          data: 'customsCode',
          allowEmpty: false,
          width: 80,
          type: 'text',
          validator: function(v, callback) {
            if (v.indexOf('0000') > -1) {
              _this.$message.warning('报关编码中存在“0000”，请确认是否正确！')
            }

            const reg = /^\d+$|^\d*\.\d+$/g
            if (v) {
              if (reg.test(v)) {
                callback(true)
              } else {
                callback(false)
                _this.$message.warning('只能输入数字和“.”')
              }
            } else {
              callback(true)
            }
          }
        },
        {
          data: 'customsClearanceCode',
          allowEmpty: false,
          width: 80,
          type: 'text',
          validator: function(v, callback) {
            if (v.indexOf('0000') > -1) {
              _this.$message.warning('清关编码中存在“0000”，请确认是否正确！')
            }

            const reg = /^\d+$|^\d*\.\d+$/g
            if (v) {
              if (reg.test(v)) {
                callback(true)
              } else {
                callback(false)
                _this.$message.warning('只能输入数字和“.”')
              }
            } else {
              callback(true)
            }
          }
        },
        {
          data: 'asin',
          width: 75,
          type: 'text'
        },
        {
          data: 'isCharged',
          type: 'text',
          width: 55
        },
        {
          data: 'model',
          allowEmpty: false,
          type: 'text'
        },
        {
          data: 'num',
          allowEmpty: false,
          type: 'numeric'

        },
        {
          data: 'measurementUnit', // 单位
          allowEmpty: false,
          type: 'dropdown',
          source: this.skuUnit
        },
        {
          data: 'perSuitNum', //
          type: 'numeric'

        },
        {
          data: 'purchasingPrice',
          allowEmpty: false,
          type: 'numeric'

        },
        {
          data: 'declareValue',
          allowEmpty: false,
          type: 'numeric'

        },
        {
          allowEmpty: false,
          // readOnly: true,
          data: 'imgUrl',
          renderer: this.coverRenderer
        }
      ]
      // 判断是否日本线
      if (isJP) {
        defaultColumns = [
          {
            data: 'shipmentId', // 指定所指列
            width: 100,
            type: 'text' // 类型
          },
          {
            data: 'referenceId',
            width: 90,
            type: 'text'
          },
          {
            data: 'sku',
            width: 120,
            type: 'autocomplete',
            source: async function(query, process) {
              console.log('query :>> ', query)
              if (_this.timer2) {
                clearTimeout(_this.timer2)
              }
              _this.timer2 = setTimeout(() => {
                console.log('query :>> ', query)
                queryApiSkuInfos({
                  currency: _this.invoiceInfoData.declareValueCurrency,
                  countryId: _this.channelFormLeft.countryId,
                  sku: query
                }).then(res => {
                  const skuArrays = res // 检索后SKU信息集合
                  console.log('skuArrays :>> ', skuArrays)
                  if (skuArrays) {
                    _this.selectSkuList = skuArrays
                    const skuCollection = [] // 存储搜索后的SKU集合
                    // selectSku = skuArrays // 将SKU信息赋值给全局变量
                    for (let i = 0; i < skuArrays.length; i++) {
                      const sku = skuArrays[i].sku
                      if (sku) {
                        skuCollection.push(sku)
                      }
                    }
                    console.log('skuCollection :>> ', skuCollection)
                    process(skuCollection)
                  }
                })
              }, 800)
            },
            strict: true,
            renderer: this.skuCellRenderer
          },
          {
            data: 'declareNameEn',
            // allowEmpty: false,
            width: 65,
            type: 'text',
            validator: function(v, callback) {
              const reg = new RegExp(
                '([\u4E00-\u9FFF]|[\u3002\uff1b\uff0c\uff1a\u201c\u201d\uff08\uff09\u3001\uff1f\u300a\u300b\uff01\u3010\u3011\uffe5])+',
                'g'
              )

              if (reg.test(v)) {
                callback(false)
                _this.$message.error('请勿包含中文字符')
              } else {
                callback(true)
              }
            }
          },
          {
            data: 'declareNameCn',
            allowEmpty: false,
            width: 65,
            type: 'text'
          },
          {
            data: 'brand',
            allowEmpty: false,
            width: 55,
            type: 'text'
          },
          {
            data: 'material',
            allowEmpty: false,
            width: 55,
            type: 'text'
          },
          {
            data: 'purpose',
            allowEmpty: false,
            width: 55,
            type: 'text'
          },
          {
            data: 'customsCode',
            allowEmpty: false,
            width: 60,
            type: 'text',
            validator: function(v, callback) {
              if (v.indexOf('0000') > -1) {
                _this.$message.warning('报关编码中存在“0000”，请确认是否正确！')
              }

              const reg = /^\d+$|^\d*\.\d+$/g
              if (v) {
                if (reg.test(v)) {
                  callback(true)
                } else {
                  callback(false)
                  _this.$message.warning('只能输入数字和“.”')
                }
              } else {
                callback(true)
              }
            }
          },
          {
            data: 'customsClearanceCode',
            allowEmpty: false,
            width: 60,
            type: 'text',
            validator: function(v, callback) {
              if (v.indexOf('0000') > -1) {
                _this.$message.warning('清关编码中存在“0000”，请确认是否正确！')
              }

              const reg = /^\d+$|^\d*\.\d+$/g
              if (v) {
                if (reg.test(v)) {
                  callback(true)
                } else {
                  callback(false)
                  _this.$message.warning('只能输入数字和“.”')
                }
              } else {
                callback(true)
              }
            }
          },
          {
            data: 'asin',
            width: 75,
            type: 'text'
          },

          {
            data: 'isCharged',
            type: 'text',
            width: 55
          },
          {
            data: 'model',
            allowEmpty: false,
            type: 'text'
          },
          {
            data: 'num',
            allowEmpty: false,
            type: 'numeric'
          },
          {
            data: 'measurementUnit', // 单位
            allowEmpty: false,
            type: 'dropdown',
            source: this.skuUnit
          },
          {
            data: 'perSuitNum', //
            type: 'numeric'
          },
          {
            data: 'fnSku',
            width: 75,
            type: 'text',
            validator: function(v, callback) {
              if (v.length > 10) {
                callback(false)
                _this.$message.error('FNSKU限制10位')
              } else {
                callback(true)
              }
            }
          },
          {
            data: 'purchasingPrice', // 采购单价
            type: 'numeric'
          },
          {
            data: 'declareValue',
            type: 'numeric' // ASIN售价
          },
          {
            data: 'distributionMaterialCount',
            type: 'numeric' // 配送料
          },
          {
            data: 'productLotCount',
            type: 'numeric' // 出品手数料
          },
          {
            data: 'imgUrl',
            renderer: this.coverRenderer
            // readOnly: true
          },
          {
            data: 'sellPriceScreenshot',
            // readOnly: true,
            renderer: this.coverRenderer
          },
          {
            data: 'incomeScreenshot',
            // readOnly: true,
            renderer: this.coverRenderer
          }
        ]
      }
      return defaultColumns
    }
  }
}
</script>

<style scoped>
/* .hot-table >>> .el-card__header {
  padding: 6px 20px;
} */
.el-card__header {
  padding: 6px 20px;
}
.handsontable >>> th {
  color: red;
}
.handsontable >>> .noRedTitle {
  color: #222;
}
.handsontable >>> .td-center {
  text-align: center; /*设置水平居中*/
  vertical-align: middle; /*设置垂直bai居中*/
}
.upload-Invoice-dialog >>> .el-dialog__body {
  padding-top: 10px;
}
</style>
<style lang="scss" scoped>
.hot-table {
  position: relative;

  .head-main {
    .head-btn {
      display: inline-block;
      width: 140px;
      height: 26px;
      text-align: center;
      line-height: 26px;
      color: #51abde;
      border: 1px solid #51abde;
      border-radius: 4px;

      cursor: pointer;
    }
    .head-btn-tips {
      color: #fbb64e;
    }
  }

  .el-upload {
    width: 100%;
    .el-upload-dragger {
      width: 100%;
    }
  }
  .tips-a {
    // display: none;
    position: absolute;
    top: 70px;
    right: 13%;
    z-index: 1001;
    background: #fff;
    // border: 1px solid #ccc;
    padding: 10px;
    border-radius: 10px;
    line-height: 2;
    box-shadow: 0 5px 5px rgba(0, 0, 0, 0.5);
    &::before {
      display: block;
      content: '';
      border-width: 8px 8px 8px 8px;
      border-style: solid;
      border-color: transparent transparent #fff transparent;

      /* 定位 */
      position: absolute;
      right: 10%;
      top: -16px;
    }
  }
  .tips-b {
    right: 7%;
  }
  .isUpload {
    text-align: center;
    color: cornflowerblue;
    cursor: pointer;
    &:hover .upload-text {
      text-decoration: underline;
      color: red;
    }
  }
  .upload-tips {
    font-size: 18px;
    color: #ccc;
  }

  .down-btn {
    margin-bottom: 10px;
    a {
      color: red;
      padding: 8px;
      &:hover {
        text-decoration: underline;
      }
    }
  }
  .upload-Invoice-dialog {
    // position: relative;
    .Invoice-dialog-tips-icon {
      position: absolute;
      top: 15.4%;
      left: 0;
      .icon-question {
        font-size: 26px;
      }
    }
  }
}
</style>
<style lang="scss">
.hot-table {
  .el-upload {
    width: 100%;
    .el-upload-dragger {
      width: 100%;
    }
  }
  .upload-img {
    height: calc(100% - 46px);
    .el-upload {
      width: 100%;
      height: 100%;
      .el-upload-dragger {
        width: 100%;
        height: 100%;
      }
    }
  }
}

.hasImg {
  display: block;
  width: 26px !important;
  height: 26px;
  margin: 0 auto;
}

.handsontable th {
  background: #fff;
  color: #2c3e50;
  text-align: left;
  font-weight: bold;
}

.el-card__body {
  color: #606266;
}
.handsontable th:first-child,
.handsontable th:nth-child(2),
.handsontable td:first-of-type,
.handsontable tr th,
.handsontable tr td,
.handsontable tr:first-child th,
.handsontable tr:first-child td {
  border-color: #ebeef5;
}
</style>
